package com.yonyou.pmclouds.problemlog.service.rmiimpl;


import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.assigninfo.entity.AssignInfoVO;
import com.yonyou.pmclouds.assigninfo.rmiitf.IAssignInfoMaintain;
import com.yonyou.pmclouds.auditlog.entity.AuditLogVO;
import com.yonyou.pmclouds.auditlog.service.IAuditLogMaintain;
import com.yonyou.pmclouds.basecom.annotation.Lock;
import com.yonyou.pmclouds.basecom.bp.processor.*;
import com.yonyou.pmclouds.basecom.bp.template.MultiInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.consts.BillTypeConst;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.copyperson.entity.CopyPersonVO;
import com.yonyou.pmclouds.copyperson.rmiitf.ICopyPersonMaintain;
import com.yonyou.pmclouds.messagenotice.rmiitf.MessageNoticeMaintain;
import com.yonyou.pmclouds.picture.rmiitf.PictureRemoteService;
import com.yonyou.pmclouds.problemlog.entity.ProblemLogBillStatus;
import com.yonyou.pmclouds.problemlog.entity.ProblemLogVO;
import com.yonyou.pmclouds.problemlog.mapper.ProblemLogMapper;
import com.yonyou.pmclouds.problemlog.process.ProblemLogBeforeAddProcess;
import com.yonyou.pmclouds.problemlog.process.ProblemLogBeforeMultiAddProcess;
import com.yonyou.pmclouds.problemlog.process.ProblemLogProjectLogPostProcess;
import com.yonyou.pmclouds.problemlog.process.RepairPassAfterProcess;
import com.yonyou.pmclouds.problemlog.service.rmiitf.ProblemLogMaintain;
import com.yonyou.pmclouds.project.processor.ProjectBillUpdateForUpdate;
import com.yonyou.pmclouds.project.processor.UpdateBillCountForInsertProcessor;
import com.yonyou.pmclouds.repairlog.entity.RepairLogVO;
import com.yonyou.pmclouds.repairlog.service.rmiitf.RepairLogService;
import com.yonyou.pmclouds.task.entity.TaskParamVO;
import com.yonyou.pmclouds.task.rmiitf.TaskRemoteService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service(version = ApplicationConsts.APPLICATION_VERSION,interfaceClass=ProblemLogMaintain.class, timeout = 4000)
public class ProblemLogMaintainImpl implements ProblemLogMaintain {
    /**
     * 需要更新的字段
     */
    private static String[] UPDATE_FIELDS={CommonFieldConst.MODIFIER, CommonFieldConst.MODIFYTIME,
            ProblemLogVO.CONTENT};
    /**
     * 整改，继续整改，通过需要更新问题记录单的状态
     */
    private static String[] UPDATE_STATUS = {ProblemLogVO.BILLSTATUS};
    @Autowired
    private ProblemLogMapper mapper;
    @Autowired
    private RepairLogService repairService;
    @Autowired
    private PictureRemoteService pictureService;
    @Autowired
    private MobileTaskInsertProcessor<ProblemLogVO> mobileTaskInsertProcessor;
    @Autowired
    private ProjectStatusCheckProcessor<ProblemLogVO> projectStatusCheckProcessor;
    @Autowired
    private TaskRemoteService taskService;
    @Autowired
    private RepairPassAfterProcess passProcess;
    @Autowired
    private MessageNoticeMaintain noticeMaintain;
    @Autowired
    private UpdateBillCountForInsertProcessor.UpdateBillCountForInsertProcessorFactory<ProblemLogVO> billCountFactory;
    @Autowired
    private ProjectBillUpdateForUpdate.ProjectBillForUpdateProcessorFactory<ProblemLogVO> billForUpdateProcessorFactory;

    @Autowired
    private MobileNoticeInsertProcessor<ProblemLogVO> mobileNoticeInsertProcessor;
    @Autowired
    private MobileNoticeInsertBatchProcessor<ProblemLogVO> mobileNoticeInsertBatchProcessor;
    @Autowired
    private IAssignInfoMaintain assignInfoMaintain;
    @Autowired
    private ICopyPersonMaintain copyPersonMaintain;
    @Autowired
    private ProblemLogProjectLogPostProcess problemLogProjectLogPostProcess;
    @Autowired
    private IAuditLogMaintain auditLogMaintain;
    @Autowired
    private DocCenterProcessor docCenterProcessor;

    @Override
    public ProblemLogVO add(ProblemLogVO vo) throws BusinessException {

        vo.setOperation(ProblemLogVO.OPERATION_ADD);

        SingleInsertBpTemplate<ProblemLogVO> bp = new SingleInsertBpTemplate<ProblemLogVO>(mapper);

        // 业务规则校验
        bp.addBeforeProcessor(new ProblemLogBeforeAddProcess());

        // 更新审计信息
        bp.addBeforeProcessor(new AuditInfoInsertProcessor<ProblemLogVO>());

        bp.addBeforeProcessor(projectStatusCheckProcessor);

        // 发送至整改人待办
        bp.addAfterProcessor(mobileTaskInsertProcessor);

        // 给抄送人发送通知
        bp.addAfterProcessor(mobileNoticeInsertProcessor);

        bp.addAfterProcessor(billCountFactory.getProcessor(BillTypeConst.PROBLEMLOG_BILLTYPE));
        //智能日志
        bp.addAfterProcessor(problemLogProjectLogPostProcess);

        ProblemLogVO returnVO =  bp.insert(vo);

        // 保存交办信息
        assignInfoMaintain.insert(getAssignInfo(vo));

        // 保存抄送人
        List<CopyPersonVO> copyPersonVOS = getCopyPersons(vo);
        if(copyPersonVOS != null && copyPersonVOS.size() > 0){
            copyPersonMaintain.insertBatch(copyPersonVOS);
        }

        // 保存图片
        pictureService.insertPictureForPub(vo, null);
        
        return returnVO;
        
    }

    private AssignInfoVO getAssignInfo(ProblemLogVO problemLogVO){
        AssignInfoVO assignInfoVO = new AssignInfoVO();
        assignInfoVO.setPkProject(problemLogVO.getPk_project());
        assignInfoVO.setPkBill(problemLogVO.getPk_problem());
        assignInfoVO.setAssignPerson(problemLogVO.getPk_rectificationer());
        assignInfoVO.setSrcBillType(problemLogVO.getBill_type());
        assignInfoVO.setLastBillTime(problemLogVO.getEnddate());
        return assignInfoVO;
    }

    private AssignInfoVO[] getAssignInfoArray(ProblemLogVO[] problemLogVOS){
        List<AssignInfoVO> assignInfoVOS = new ArrayList<>();
        for(ProblemLogVO problemLogVO : problemLogVOS){
            assignInfoVOS.add(getAssignInfo(problemLogVO));
        }
        return assignInfoVOS.toArray(new AssignInfoVO[]{});
    }

    private List<CopyPersonVO> getCopyPersons(ProblemLogVO problemLogVO){
        List<CopyPersonVO> copyPersonVOList = problemLogVO.getCopyPersonVOS();
        if(copyPersonVOList != null && copyPersonVOList.size() > 0){
            for(CopyPersonVO copyPersonVO : copyPersonVOList){
                copyPersonVO.setPkBill(problemLogVO.getPk_problem());
            }
        }
        return copyPersonVOList;
    }

    private List<CopyPersonVO> getCopyPersons(ProblemLogVO[] problemLogVOS){
        List<CopyPersonVO> result = new ArrayList<>();
        for(ProblemLogVO problemLogVO : problemLogVOS){
            List<CopyPersonVO> copyPersonVOList = problemLogVO.getCopyPersonVOS();
            if(copyPersonVOList != null && copyPersonVOList.size() > 0) {
                for(CopyPersonVO copyPersonVO : copyPersonVOList){
                    copyPersonVO.setPkBill(problemLogVO.getPk_problem());
                }
                result.addAll(copyPersonVOList);
            }
        }

        return result;
    }

    @Override
    public String delete(String pk_problemlog) throws BusinessException {
        if(StringUtils.isEmpty(pk_problemlog)) {
            throw new BusinessException("传入的要删除的问题记录单为空");
        }
        ProblemLogVO tempVO = new ProblemLogVO();
        tempVO.setPk_problem(pk_problemlog);
        SingleDeleteBpTemplate<ProblemLogVO> bp = new SingleDeleteBpTemplate<>(mapper);
        bp.addBeforeProcessor(new AuditInfoInsertProcessor<ProblemLogVO>());
        bp.delete(tempVO);
        return pk_problemlog;
    }
    @Override
    @Lock
    public ProblemLogVO update(ProblemLogVO vo) throws BusinessException {
        SingleUpdateBpTemplate<ProblemLogVO> bp = new SingleUpdateBpTemplate<>(mapper, UPDATE_FIELDS);
        bp.addAfterProcessor(billForUpdateProcessorFactory.getProcessor(BillTypeConst.PROBLEMLOG_BILLTYPE));
        bp.addBeforeProcessor(new AuditInfoUpdateProcessor<ProblemLogVO>());
        return bp.update(vo);
    }
    @Override
    public ProblemLogVO repair(ProblemLogVO problemLogVO) throws BusinessException {
        RepairLogVO[] vos = problemLogVO.getRepairlogs();
        if(vos == null || vos.length <= 0){
            return null;
        }
        // 添加本次整改记录
        RepairLogVO vo = vos[0];
        vo.setRepair_time(new Date());
        vo.setBillstatus(ProblemLogBillStatus.STATUS_INIT);

        problemLogVO.setOperation(ProblemLogVO.OPERATION_REPAIR);

        vo.setPk_project(problemLogVO.getPk_project());
        repairService.add(vo);
        problemLogVO.setBillstatus(ProblemLogBillStatus.STATUS_ACCEPTING);
        // 整改人整改后，设定问题记录单的状态为待验收
        updateService(problemLogVO, UPDATE_STATUS);
       // 发送代办给问题发起人
        TaskParamVO paramVO = new TaskParamVO(problemLogVO.getPk_rectificationer(),problemLogVO.getCreator(),null);
        taskService.insertWithBuziVO(problemLogVO, paramVO);
        return problemLogVO;
    }
    @Override
    public ProblemLogVO repairTo(ProblemLogVO problemLogVO) throws BusinessException {
        RepairLogVO[] repairLogVOS = problemLogVO.getRepairlogs();
        if(repairLogVOS == null || repairLogVOS.length <= 0){
            return null;
        }
        RepairLogVO vo = repairLogVOS[0];
        // 修改【问题记录单】的状态为待整改
        problemLogVO.setOperation(ProblemLogVO.OPERATION_NO_PASS);
        problemLogVO.setBillstatus(ProblemLogBillStatus.STATUS_REPAIRING);
        ProblemLogVO problemVO = updateService(problemLogVO, UPDATE_STATUS);
        // 修改【本次整改记录】的状态与意见
        RepairLogVO repairLogVO = repairService.queryOne(vo.getPk_repair());
        repairLogVO.setAudit(vo.getAudit());
        repairLogVO.setBillstatus(ProblemLogBillStatus.STATUS_NOT_PASS);
        repairService.update(repairLogVO, new String[]{RepairLogVO.AUDIT,RepairLogVO.BILLSTATUS});

        // 新增验收记录
        AuditLogVO auditLogVO = vo.getAuditLogVO();
        auditLogVO.setPkBill(problemLogVO.getPk_problem());
        auditLogVO.setPkProject(problemLogVO.getPk_project());
        auditLogVO.setPkRepairLog(vo.getPk_repair());
        auditLogMaintain.add(auditLogVO);

        // 发送代办给整改人
        TaskParamVO paramVO = new TaskParamVO(problemLogVO.getCreator(),problemLogVO.getPk_rectificationer(),null);
        taskService.insertWithBuziVO(problemLogVO, paramVO);

        return problemVO;
    }
    @Override
    @Lock
    public ProblemLogVO pass(ProblemLogVO problemLogVO) throws BusinessException {
        problemLogVO.setOperation(ProblemLogVO.OPERATION_PASS);
        SingleUpdateBpTemplate<ProblemLogVO> bp = new SingleUpdateBpTemplate<ProblemLogVO>(mapper, UPDATE_STATUS);
        // 修改本次整改记录的状态为通过
        bp.addAfterProcessor(passProcess);
        bp.addAfterProcessor(mobileNoticeInsertProcessor);
        problemLogVO.setBillstatus(ProblemLogBillStatus.STATUS_END);
        bp.addAfterProcessor(billForUpdateProcessorFactory.getProcessor(BillTypeConst.PROBLEMLOG_BILLTYPE));
        bp.addAfterProcessor(docCenterProcessor);
        bp.update(problemLogVO);
        // 完成待办任务
        taskService.finishTask(problemLogVO.getPk_problem(), problemLogVO.getCreator(), ProblemLogBillStatus.STATUS_END);

        return problemLogVO;
    }

    @Override
    public ProblemLogVO[] add(ProblemLogVO[] vos) throws BusinessException {
        if(vos == null || vos.length == 0) return vos;
        MultiInsertBpTemplate<ProblemLogVO> bp = new MultiInsertBpTemplate<ProblemLogVO>(mapper);
        // 业务规则校验
        bp.addBeforeProcessor(new ProblemLogBeforeMultiAddProcess());
        // 更新审计信息
        bp.addBeforeProcessor(new AuditInfoInsertMultiProcessor<ProblemLogVO>());
        bp.addAfterProcessor(billCountFactory.getProcessor(BillTypeConst.PROBLEMLOG_BILLTYPE));
        bp.addAfterProcessor(mobileNoticeInsertBatchProcessor);
        vos = bp.insert(vos);
        // 新增完了后上传图片
        pictureService.insertPicturesForPub(vos, null);

        // 保存交办信息
        assignInfoMaintain.insertBatch(getAssignInfoArray(vos));

        // 保存抄送人
        List<CopyPersonVO> copyPersonVOList = getCopyPersons(vos);
        if(copyPersonVOList != null && copyPersonVOList.size() > 0){
            copyPersonMaintain.insertBatch(copyPersonVOList);
        }

        //TODO: 发送至整改人待办
        taskService.insertWithBuziVOs(vos, null);
        return vos;
    }
    
    @Lock
    private ProblemLogVO updateService(ProblemLogVO vo,String[] updateFileds) throws BusinessException {
        if(vo == null) {
            return null;
        }
        SingleUpdateBpTemplate<ProblemLogVO> bp = new SingleUpdateBpTemplate<>(mapper, updateFileds);
        bp.addBeforeProcessor(new AuditInfoUpdateProcessor<ProblemLogVO>());
        bp.addAfterProcessor(mobileNoticeInsertProcessor);
        bp.addAfterProcessor(billForUpdateProcessorFactory.getProcessor(BillTypeConst.PROBLEMLOG_BILLTYPE));

        return bp.update(vo);
    }

    @Override
    public ProblemLogVO updateAssignInfo(ProblemLogVO vo) throws BusinessException {
        vo.setOperation(ProblemLogVO.OPERATION_ASSIGN);

        ProblemLogVO oldLogVO = mapper.getById(vo.getPk_problem());
        if(oldLogVO == null)
            return null;

        vo.setBillstatus(oldLogVO.getBillstatus());
        vo.setBill_type(oldLogVO.getBill_type());
        vo.setPk_project(oldLogVO.getPk_project());
        vo.setModifier(oldLogVO.getModifier());
        vo.setCreator(oldLogVO.getCreator());

        AssignInfoVO assignInfoVO = getAssignInfo(vo);

        // 如果修改了计划完成时间，则记录下修改时间
        if(checkEndDate(oldLogVO, vo)){
            assignInfoVO.setLastBillTime(oldLogVO.getEnddate());
            assignInfoVO.setThisBillTime(vo.getEnddate());
        }

        assignInfoMaintain.insert(assignInfoVO);

        String[] UPDATE_FIELDS={CommonFieldConst.MODIFIER, CommonFieldConst.MODIFYTIME,
                ProblemLogVO.PK_RECTIFICATIONER, ProblemLogVO.END_DATE};
        SingleUpdateBpTemplate<ProblemLogVO> bp = new SingleUpdateBpTemplate<>(mapper, UPDATE_FIELDS);
        bp.addBeforeProcessor(new AuditInfoUpdateProcessor<ProblemLogVO>());
        bp.addAfterProcessor(mobileNoticeInsertProcessor);

        // 给整改人发送待办
        TaskParamVO paramVO = new TaskParamVO(oldLogVO.getPk_rectificationer(),vo.getPk_rectificationer(),null);
        taskService.insertWithBuziVO(vo, paramVO);

        return bp.update(vo);
    }

    private boolean checkEndDate(ProblemLogVO oldLogVO, ProblemLogVO vo){
        Date oldEndDate = oldLogVO.getEnddate();
        boolean flag = false;
        if(oldEndDate == null && vo.getEnddate() != null){
            flag = true;
        }else if(oldEndDate != null && vo.getEnddate() != null){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(oldEndDate);
            int oldYear = calendar.get(Calendar.YEAR);
            int oldMonth = calendar.get(Calendar.MONTH);
            int oldDay = calendar.get(Calendar.DAY_OF_MONTH);
            calendar.setTime(vo.getEnddate());
            int newYear = calendar.get(Calendar.YEAR);
            int newMonth = calendar.get(Calendar.MONTH);
            int newDay = calendar.get(Calendar.DAY_OF_MONTH);
            if(oldYear != newYear || oldMonth != newMonth || oldDay != newDay){
                flag = true;
            }
        }
        return flag;
    }
}
